home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
mtools.lha
/
mtools-2.0.7
/
mformat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-10
|
6KB
|
249 lines
/*
* Add an MSDOS filesystem to a low level formatted diskette.
*
* Emmet P. Gray US Army, HQ III Corps & Fort Hood
* ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
* fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing
* Environmental Management Office
* Fort Hood, TX 76544-5057
*/
#include <stdio.h>
#include <ctype.h>
#include "msdos.h"
#include "patchlevel.h"
int fd, dir_dirty, dir_entries;
long dir_chain[MAX_DIR_SECS];
unsigned char *dir_buf;
main(argc, argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
extern struct device devices[];
struct bootsector boot;
int i, c, oops, tracks, heads, sectors, fat_len, dir_len, clus_size;
int tot_sectors, num_clus, fat_guess;
long time(), now, lseek();
char drive, *name, *expand();
char *strncpy(), *memset(), *memcpy();
unsigned char media, label[12], buf[MSECTOR_SIZE];
struct device *dev;
struct directory *dir, *mk_entry();
void exit(), perror();
oops = 0;
tracks = 0;
heads = 0;
sectors = 0;
label[0] = '\0';
/* get command line options */
while ((c = getopt(argc, argv, "t:h:s:l:")) != EOF) {
switch (c) {
case 't':
tracks = atoi(optarg);
break;
case 'h':
heads = atoi(optarg);
break;
case 's':
sectors = atoi(optarg);
break;
case 'l':
sprintf((char *) label, "%-11.11s", optarg);
break;
default:
oops = 1;
break;
}
}
if (oops || (argc - optind) != 1) {
fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
fprintf(stderr, "Usage: %s [-t tracks] [-h heads] [-s sectors] [-l label] device\n", argv[0]);
exit(1);
}
drive = argv[argc -1][0];
if (islower(drive))
drive = toupper(drive);
/* check out the drive letter */
dev = devices;
while (dev->drive) {
if (dev->drive == drive)
break;
dev++;
}
if (!dev->drive) {
fprintf(stderr, "Drive '%c:' not supported\n", drive);
exit(1);
}
if (dev->tracks == 0) {
fprintf(stderr, "Non-removable media is not supported\n");
exit(1);
}
/* find the right one */
if (!dev->gioctl) {
while (dev->drive == drive) {
if ((!tracks || dev->tracks == tracks) && (!heads || dev->heads == heads) && (!sectors || dev->sectors == sectors))
break;
dev++;
}
}
if (dev->drive != drive) {
fprintf(stderr, "%s: Paramaters not supported\n", argv[0]);
exit(1);
}
/* open the device */
name = expand(dev->name);
if ((fd = open(name, 2 | dev->mode)) < 0) {
perror("init: open");
exit(1);
}
/* fill in the blanks */
if (!tracks)
tracks = dev->tracks;
if (!heads)
heads = dev->heads;
if (!sectors)
sectors = dev->sectors;
/* set parameters, if needed */
if (dev->gioctl) {
if ((*(dev->gioctl)) (fd, tracks, heads, sectors))
exit(1);
}
/* do a "test" read */
if (read(fd, (char *) buf, MSECTOR_SIZE) != MSECTOR_SIZE) {
fprintf(stderr, "%s: Error reading from '%s', wrong parameters?\n", argv[0], name);
exit(1);
}
/* get the parameters */
tot_sectors = tracks * heads * sectors;
switch (tot_sectors) {
case 320: /* 40t * 1h * 8s = 160k */
media = 0xfe;
clus_size = 1;
dir_len = 4;
fat_len = 1;
break;
case 360: /* 40t * 1h * 9s = 180k */
media = 0xfc;
clus_size = 1;
dir_len = 4;
fat_len = 2;
break;
case 640: /* 40t * 2h * 8s = 320k */
media = 0xff;
clus_size = 2;
dir_len = 7;
fat_len = 1;
break;
case 720: /* 40t * 2h * 9s = 360k */
media = 0xfd;
clus_size = 2;
dir_len = 7;
fat_len = 2;
break;
case 1440: /* 80t * 2h * 9s = 720k */
media = 0xf9;
clus_size = 2;
dir_len = 7;
fat_len = 3;
break;
case 2400: /* 80t * 2h * 15s = 1.2m */
media = 0xf9;
clus_size = 1;
dir_len = 14;
fat_len = 7;
break;
case 2880: /* 80t * 2h * 18s = 1.44m */
media = 0xf0;
clus_size = 1;
dir_len = 14;
fat_len = 9;
break;
default: /* a non-standard format */
media = 0xf0;
if (heads == 1)
clus_size = 1;
else
clus_size = (tot_sectors > 2000) ? 1 : 2;
if (heads == 1)
dir_len = 4;
else
dir_len = (tot_sectors > 2000) ? 14 : 7;
/*
* Estimate the fat length, then figure it out. The
* 341 is the number of 12 bit fat entries in a sector.
*/
fat_guess = ((tot_sectors / clus_size) / 341.0) + 0.95;
num_clus = (tot_sectors -dir_len - (2 * fat_guess) -1) / clus_size;
fat_len = (num_clus / 341.0) + 1;
break;
}
/* the boot sector */
memset((char *) &boot, '\0', MSECTOR_SIZE);
boot.jump[0] = 0xeb;
boot.jump[1] = 0x44;
boot.jump[2] = 0x90;
strncpy((char *) boot.banner, "Mtools ", 8);
boot.secsiz[0] = 512 % 0x100;
boot.secsiz[1] = 512 / 0x100;
boot.clsiz = (unsigned char) clus_size;
boot.nrsvsect[0] = 1;
boot.nrsvsect[1] = 0;
boot.nfat = 2;
boot.dirents[0] = (dir_len * 16) % 0x100;
boot.dirents[1] = (dir_len * 16) / 0x100;
boot.psect[0] = tot_sectors % 0x100;
boot.psect[1] = tot_sectors / 0x100;
boot.descr = media;
boot.fatlen[0] = fat_len % 0x100;
boot.fatlen[1] = fat_len / 0x100;
boot.nsect[0] = sectors % 0x100;
boot.nsect[1] = sectors / 0x100;
boot.nheads[0] = heads % 0x100;
boot.nheads[1] = heads / 0x100;
/* write the boot */
lseek(fd, 0L, 0);
write(fd, (char *) &boot, MSECTOR_SIZE);
/* first fat */
memset((char *) buf, '\0', MSECTOR_SIZE);
buf[0] = media;
buf[1] = 0xff;
buf[2] = 0xff;
write(fd, (char *) buf, MSECTOR_SIZE);
memset((char *) buf, '\0', MSECTOR_SIZE);
for (i = 1; i < fat_len; i++)
write(fd, (char *) buf, MSECTOR_SIZE);
/* second fat */
buf[0] = media;
buf[1] = 0xff;
buf[2] = 0xff;
write(fd, (char *) buf, MSECTOR_SIZE);
memset((char *) buf, '\0', MSECTOR_SIZE);
for (i = 1; i < fat_len; i++)
write(fd, (char *) buf, MSECTOR_SIZE);
/* the root directory */
if (label[0] != '\0') {
time(&now);
dir = mk_entry(label, 0x08, 0, 0L, now);
memcpy((char *) buf, (char *) dir, MDIR_SIZE);
}
write(fd, (char *) buf, MSECTOR_SIZE);
memset((char *) buf, '\0', MSECTOR_SIZE);
for (i = 1; i < dir_len; i++)
write(fd, (char *) buf, MSECTOR_SIZE);
close(fd);
exit(0);
}
/* hooks for the missing parts */
void disk_write() {}